#pragma once
#include "Socket.hpp"
#include "InetAddr.hpp"
#include <memory>
#include <functional>
#include <json/json.h>

using namespace SocketModule;

// 序列化和反序列化
// x=10 y=20 cal=*
class Request
{
public:
    Request()
    {
    }
    // {"x"=5 "y"=10 "oper"='+'}
    bool Deserialize(const std::string &data)
    {
        Json::Reader reader;
        Json::Value root;

        bool success = reader.parse(data, root);
        if (!success)
            return false;
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }
    std::string Serialize() const
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string result = writer.write(root);
        return result;
    }
    int X() const { return _x; }
    int Y() const { return _y; }
    char Oper() const { return _oper; }

    void SetRequest(int x, int y, char oper)
    {
        _x = x;
        _y = y;
        _oper = oper;
    }

    ~Request()
    {
    }

private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
    {
    }
    // {"result"=5 "code"=10}
    bool Deserialize(const std::string &data)
    {
        Json::Reader reader;
        Json::Value root;
        bool success = reader.parse(data, root);
        if (!success)
            return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
    }
    std::string Serialize() const
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string result = writer.write(root);
        return result;
    }
    int Result() { return _result; }
    int Code() { return _code; }

    void SetResponse(int result, int code)
    {
        _result = result;
        _code = code;
    }

    ~Response()
    {
    }

private:
    int _result; // 计算结果
    int _code;   // 信号，为0结果有效，其他情况表示出异常
};

class Protocol
{
private:
    using task_t = std::function<Response(const Request &)>;
    static const std::string sep;

public:
    Protocol()
    {
    }
    Protocol(task_t task)
        : _task(task)
    {
    }

    // 添加报头
    // 50\r\n{xxxxxx}\r\n
    void Encode(std::string &in) const
    {
        // 当前{xxxxxx}
        size_t len = in.size();
        // 头插：50\r\n
        in.insert(0, std::to_string(len) + sep);
        in.append(sep);
    }

    // 50\r\n{"x"=5 "y"=10 "oper"='+'}\r\n
    std::string Decode(std::string &data) const
    {
        size_t pos = data.find(sep);
        // 分割符都没找到，一定不完整
        if (pos == std::string::npos)
            return std::string();
        // 读到分隔符，分隔符前面的一定是数字（完整一条一条地截取）
        std::string len_str = data.substr(0, pos);
        int len = std::stoi(len_str);
        // 计算出总长度
        int total = len_str.size() + 2 * sep.size() + len;
        if (data.size() < total) // 不完整，不截取
            return std::string();
        // 一定有一条及以上，截取，原data删除一条
        std::string result = data.substr(len_str.size() + sep.size(), len_str.size() + sep.size() + len);
        data.erase(0, total);
        return result;
    }

    std::string Execute(std::string &out) const
    {
        std::string ret = Decode(out);
        if (ret == std::string())
            return std::string();
        // 取到了一条完整数据，进行反序列化
        Request req;
        bool success = req.Deserialize(ret);
        if (!success)
        {
            LOG(LogLevel::WARNING) << "Deserialize error";
            return std::string();
        }
        // 数据给具体的回调业务处理
        Response resp = _task(req);
        // 处理完结果序列化
        std::string resultstr = resp.Serialize();
        // 添加protocol报头
        Encode(resultstr);
        return resultstr;
    }

    ~Protocol()
    {
    }

private:
    task_t _task;
};

const std::string Protocol::sep = "\r\n";